import os
import re
import subprocess
import multiprocessing as mp
import json

# WeBrain & Norm Assess ALGORITHM
class ALGO:

    def __init__(self, input, output, combs_project_id, prefix, suffix):
        #self.docker_cmd = "docker run --rm=true "
        self.algo = ""
        #self.algo = "fb_EEG_Power"
        self.Input = input + " "
        self.Output = output + " "
        self.Combs_project_id = combs_project_id + " "
        #self.image = "fb_eeg:v1 "
        self.prefix = prefix
        self.suffix = suffix

    def get_MntDir(self, *inputs):
        """ Get Dir for Docker to Mount
        self.get_MntDir(self.Input, self.Output) ---  -v Input:Input -v Output:Output
        Returns:
            string: Mount Dir
        """
        S = set()
        for input in inputs:
            input_items = re.split('\,|\ ', input)
            for item in input_items:
                # input: {.zip, .mat}
                if item.endswith(".zip") or item.endswith(".mat") or item.endswith(".txt") or item.endswith(
                        ".csv") or item.endswith(".ced"):
                    S.add(os.path.dirname(item))
                elif os.path.isdir(item):
                    S.add(item)

        mount_dir = ""
        for s in S:
            mount_dir += "-v " + s + ":" + s + " "

        return mount_dir

    def get_Cmd(self):
        """ Create CMD For Module Subprocess

        Returns:
            string: Command
        """
        raise NotImplementedError

    def show_Para(self):
        """ Show All Parameters of Algorithm|Pipeline
        """

        print("**** Show Parameters ****")

        for name, value in vars(self).items():
            print("{0}: {1}".format(name, value))

        print("*************************")

    def run_Cmd(self):
        """ Use Module Subprocess to Run CMD

        Returns:
            string: Path of Results Files
        """
        res = subprocess.run(self.get_Cmd(), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        # Run Successfully
        if res.returncode == 0:
            # No File Skipped
            res_file = ""
            if self.baseflag == "1 ":
                res_file = res_file + self.basefile + ","
            else:
                res_file = res_file + self.Output[0:-1] + "/" + self.prefix + self.suffix + ","

            return res_file[0:-1]
        else:
            return "-1"

    def update_Params(self, params_file):
        with open(params_file) as json_file:
            conf = json.load(json_file)
            if self.algo in conf.keys():
                conf = conf[self.algo]
            else:
                return

            for name, _ in vars(self).items():
                if name in conf:
                    setattr(self, name, conf[name] + " ")

# fb_EEG_network
class network(ALGO):

    def __init__(self, input, output, combs_project_id):
        ALGO.__init__(self, input, output, combs_project_id, "", "feedback_results.mat")
        self.algo = "fb_EEG_network"
        self.algo_bin = "/M_script/feedback_EEG_network "
        self.QAFlag = "0 "
        self.thre_ODQ = "80 "
        self.passband = "'[1,60]' "
        self.badChannelInterploateFlag = "1 "
        self.residualArtifactRemovalFlag = "4 "
        #self.WindowSeconds = "1 "
        self.chanlocfile = "/M_script/lib/zeng-31.ced "
        self.bandLimit = "'[4,8]' "
        self.epochLenth = "'[]' "
        self.proportion = "0 "
        self.seleChanns = "'all' "
        self.method = "'psi' "
        self.N_maskfile = "/M_script/lib/mask_zone.mat "
        self.SaveFlag = "'2' "
        self.evaluFlag = "'0' "
        self.new_batch = "'1' "
        self.combat_network = "/M_script/lib/network_combat.mat "
        self.centsfile = "/M_script/lib/cents_network.mat "
        self.basefile = "/FB/result_base/feedback_base.mat"
        self.baseflag = "0 "

    def get_Cmd(self):
        self.update_Params("/FB/data/fb_params.conf")
        return self.algo_bin + self.Input + self.Output \
            + self.QAFlag + self.thre_ODQ + self.passband + self.badChannelInterploateFlag + self.residualArtifactRemovalFlag \
            + self.chanlocfile + self.bandLimit + self.epochLenth + self.proportion + self.seleChanns + self.method + self.N_maskfile \
            + self.SaveFlag + self.evaluFlag + self.new_batch + self.combat_network + self.centsfile + self.basefile + self.baseflag


# fb_EEG_Power
class Power(ALGO):

    def __init__(self, input, output, combs_project_id):
        ALGO.__init__(self, input, output, combs_project_id, "", "feedback_results.mat")
        self.algo = "fb_EEG_Power"
        self.algo_bin = "/M_script/feedback_EEG_power "
        self.QAFlag = "0 "
        self.thre_ODQ = "80 "
        self.passband = "'[1,60]' "
        self.badChannelInterploateFlag = "1 "
        self.residualArtifactRemovalFlag = "4 "
        #self.WindowSeconds = "1 "
        self.chanlocfile = "/M_script/lib/zeng-31.ced "
        self.bandLimit = "'[4,8]' "
        self.bandName = "theta "
        self.proportion = "0 "
        self.selechanns = "'F3,F4,FC1,FC2,CZ' "
        self.SaveFlag = "2 "
        self.evaluFlag = "'0' "
        self.new_batch = "1 "
        self.combat_power = "/M_script/lib/power_combat.mat "
        self.centsfile = "/M_script/lib/cents_power.mat "
        self.basefile = "/FB/result_base/feedback_base.mat"
        self.baseflag = "0 "
	
    def get_Cmd(self):
        self.update_Params("/FB/data/fb_params.conf")
        return self.algo_bin + self.Input + self.Output \
            + self.QAFlag + self.thre_ODQ + self.passband + self.badChannelInterploateFlag + self.residualArtifactRemovalFlag \
            + self.chanlocfile + self.bandLimit + self.bandName + self.proportion + self.selechanns + self.SaveFlag \
            + self.evaluFlag + self.new_batch + self.combat_power + self.centsfile + self.basefile + self.baseflag

def fb_EEG_Power(input, output, combs_project_id):
    power = Power(input, output, combs_project_id)
    print(power.get_Cmd())
    power_res = power.run_Cmd()
    print(power_res)

def fb_EEG_network(input, output, combs_project_id):
    netwk = network(input, output, combs_project_id)
    print("[command] --> " + netwk.get_Cmd())
    network_res = netwk.run_Cmd()
    print("[resFile] --> " + network_res)

def main():
    fb_EEG_network("fb_0_5.mat", "/home/skye/FB/results", "4399")
    fb_EEG_Power("fb_0_5.mat", "/home/skye/FB/results1", "4399")

if __name__ == '__main__':
    main()
